export class EzGameJsonEntityCodecs{
    public  encoder = new TextEncoder();
    public  decoder = new TextDecoder();
    private supported:boolean = false;
    private empty:Uint8Array = new Uint8Array(0);
    private static ins:EzGameJsonEntityCodecs = new EzGameJsonEntityCodecs();
    constructor(){
        try {
            this.encoder = new TextEncoder();
            this.decoder = new TextDecoder();
            this.supported = true;
          } catch (error) {
            this.supported = false;
            console.warn('TextEncoder/TextDecoder not supported, using fallback');
          }
    }
    public static entityDecoder<T>(data:Uint8Array):T{
        if(data == null){
            return {} as T;
        }
        if (EzGameJsonEntityCodecs.ins.supported) {
            let str =  EzGameJsonEntityCodecs.ins.decoder.decode(data);
            return JSON.parse(str) as T;
          } else {
            // 降级方案
            let str =  EzGameJsonEntityCodecs.ins.fallbackUint8ArrayToString(data);
            return JSON.parse(str) as T;
          }
    }

    public static entityEncoder<T>(data:T):Uint8Array{
        if(data == null){
            return EzGameJsonEntityCodecs.ins.empty;
        }
        let str = JSON.stringify(data);
        if (EzGameJsonEntityCodecs.ins.supported) {
            return EzGameJsonEntityCodecs.ins.encoder.encode(str);
          } else {
            // 降级方案
            return EzGameJsonEntityCodecs.ins.fallbackStringToUint8Array(str);
          }
    }

    fallbackStringToUint8Array(str) {
        const utf8 = unescape(encodeURIComponent(str));
        const arr = new Uint8Array(utf8.length);
        for (let i = 0; i < utf8.length; i++) {
          arr[i] = utf8.charCodeAt(i);
        }
        return arr;
    }

    fallbackUint8ArrayToString(uint8Array) {
        const utf8 = String.fromCharCode.apply(null, uint8Array);
        return decodeURIComponent(escape(utf8));
    }

    public static createEntity(type:new (...any)=>any):any{
        return new type();

    }
}